const socketIo = require('socket.io');
const path = require('path');
const DataStore = require('../utils/dataStore');
const logger = require('../utils/logger');
const config = require('../config');

/**
 * 聊天服务
 * 处理WebSocket通信和聊天功能
 */
class ChatService {
  constructor() {
    // 初始化数据存储
    this.dataStore = new DataStore(path.join(__dirname, '../../', config.dataFiles.chat));
    this.io = null;
    this.connectedClients = new Map();
    this.initialized = false;
  }

  /**
   * 设置WebSocket服务器
   * @param {Object} server - HTTP服务器实例
   */
  setWebSocketServer(server) {
    if (this.io) {
      logger.warn('WebSocket服务器已经设置，忽略重复设置');
      return;
    }

    // 创建Socket.IO实例
    this.io = socketIo(server, {
      cors: {
        origin: config.cors.origin,
        methods: config.cors.methods,
        allowedHeaders: config.cors.allowedHeaders,
        credentials: true
      }
    });

    // 初始化数据存储
    this.dataStore.init().then(() => {
      this.initialized = true;
      logger.info('聊天服务初始化完成');
    }).catch(err => {
      logger.error(`聊天服务初始化失败: ${err.message}`);
    });

    // 设置连接事件处理
    this.io.on('connection', (socket) => this.handleConnection(socket));

    logger.info('WebSocket服务器已设置');
  }

  /**
   * 处理新的WebSocket连接
   * @param {Object} socket - Socket.IO套接字对象
   */
  handleConnection(socket) {
    logger.info(`新的WebSocket连接: ${socket.id}`);

    // 存储客户端信息
    this.connectedClients.set(socket.id, {
      id: socket.id,
      username: '访客',
      connectedAt: new Date()
    });

    // 发送欢迎消息
    socket.emit('welcome', {
      message: '欢迎使用聊天服务！',
      timestamp: new Date().toISOString()
    });

    // 发送历史消息
    this.sendChatHistory(socket);

    // 设置事件处理器
    socket.on('message', (data) => this.handleMessage(socket, data));
    socket.on('typing', (data) => this.handleTyping(socket, data));
    socket.on('setUsername', (data) => this.handleSetUsername(socket, data));
    socket.on('disconnect', () => this.handleDisconnect(socket));
  }

  /**
   * 发送聊天历史记录
   * @param {Object} socket - Socket.IO套接字对象
   */
  async sendChatHistory(socket) {
    try {
      if (!this.initialized) {
        await this.dataStore.init();
        this.initialized = true;
      }

      // 获取最近的消息（最多50条）
      const messages = await this.dataStore.getAll();
      const recentMessages = messages.slice(-50);

      socket.emit('chatHistory', recentMessages);
      logger.debug(`已发送聊天历史记录给客户端: ${socket.id}`);
    } catch (error) {
      logger.error(`发送聊天历史记录失败: ${error.message}`);
      socket.emit('error', { message: '获取聊天历史记录失败' });
    }
  }

  /**
   * 处理收到的消息
   * @param {Object} socket - Socket.IO套接字对象
   * @param {Object} data - 消息数据
   */
  async handleMessage(socket, data) {
    try {
      // 验证消息格式
      if (!data || !data.content || typeof data.content !== 'string') {
        socket.emit('error', { message: '无效的消息格式' });
        return;
      }

      // 获取客户端信息
      const client = this.connectedClients.get(socket.id);
      if (!client) {
        socket.emit('error', { message: '客户端未注册' });
        return;
      }

      // 创建消息对象
      const message = {
        id: this.dataStore.generateId(),
        content: data.content.trim(),
        sender: {
          id: socket.id,
          username: client.username
        },
        timestamp: new Date().toISOString(),
        type: data.type || 'text'
      };

      // 保存消息
      if (!this.initialized) {
        await this.dataStore.init();
        this.initialized = true;
      }
      await this.dataStore.add(message);

      // 广播消息给所有客户端
      this.io.emit('message', message);
      logger.debug(`广播消息: ${message.id} 来自 ${client.username}`);
    } catch (error) {
      logger.error(`处理消息失败: ${error.message}`);
      socket.emit('error', { message: '处理消息失败' });
    }
  }

  /**
   * 处理正在输入状态
   * @param {Object} socket - Socket.IO套接字对象
   * @param {Object} data - 状态数据
   */
  handleTyping(socket, data) {
    const client = this.connectedClients.get(socket.id);
    if (!client) return;

    // 广播正在输入状态（除了发送者）
    socket.broadcast.emit('typing', {
      userId: socket.id,
      username: client.username,
      isTyping: !!data.isTyping
    });
  }

  /**
   * 处理用户名设置
   * @param {Object} socket - Socket.IO套接字对象
   * @param {Object} data - 用户名数据
   */
  handleSetUsername(socket, data) {
    if (!data || !data.username || typeof data.username !== 'string') {
      socket.emit('error', { message: '无效的用户名' });
      return;
    }

    const username = data.username.trim();
    if (username.length < 2 || username.length > 20) {
      socket.emit('error', { message: '用户名长度必须在2-20个字符之间' });
      return;
    }

    // 更新客户端信息
    const client = this.connectedClients.get(socket.id);
    if (client) {
      const oldUsername = client.username;
      client.username = username;
      this.connectedClients.set(socket.id, client);

      // 确认用户名更改
      socket.emit('usernameSet', { username });
      
      // 广播用户名更改
      this.io.emit('userUpdate', {
        userId: socket.id,
        oldUsername,
        newUsername: username
      });
      
      logger.info(`用户名已更改: ${socket.id} 从 "${oldUsername}" 到 "${username}"`);
    }
  }

  /**
   * 处理客户端断开连接
   * @param {Object} socket - Socket.IO套接字对象
   */
  handleDisconnect(socket) {
    const client = this.connectedClients.get(socket.id);
    if (client) {
      // 广播用户离开消息
      this.io.emit('userLeft', {
        userId: socket.id,
        username: client.username
      });
      
      // 移除客户端信息
      this.connectedClients.delete(socket.id);
      logger.info(`客户端断开连接: ${socket.id} (${client.username})`);
    }
  }

  /**
   * 获取当前在线用户列表
   * @returns {Array} 在线用户数组
   */
  getOnlineUsers() {
    return Array.from(this.connectedClients.values()).map(client => ({
      id: client.id,
      username: client.username,
      connectedAt: client.connectedAt
    }));
  }

  /**
   * 发送系统消息
   * @param {string} content - 消息内容
   */
  async sendSystemMessage(content) {
    try {
      if (!this.io) {
        logger.warn('WebSocket服务器未设置，无法发送系统消息');
        return;
      }

      // 创建系统消息
      const message = {
        id: this.dataStore.generateId(),
        content,
        sender: {
          id: 'system',
          username: '系统'
        },
        timestamp: new Date().toISOString(),
        type: 'system'
      };

      // 保存消息
      if (!this.initialized) {
        await this.dataStore.init();
        this.initialized = true;
      }
      await this.dataStore.add(message);

      // 广播系统消息
      this.io.emit('message', message);
      logger.info(`已发送系统消息: ${content}`);
    } catch (error) {
      logger.error(`发送系统消息失败: ${error.message}`);
    }
  }
}

// 导出单例
module.exports = new ChatService();